﻿using System.Linq;
using Foxit.PDF;
using Foxit.PDF.PageElements;
using Sustainalytics.Reporting.Framework;
using Sustainalytics.Utils;

namespace Sustainalytics.ReportGenerator.BL
{
    public class TearSheetControversiesSection : PdfReportSectionGenerator
    {
        private const float _sectionNameFontSize = 12f;

        public override void ComposeSectionContent()
        {
            const float startPosition = 130f;

            var page = _report.NewPage();
            _report.Pages.Add(page);


            AddHeaderToPage(page);

            AddHighestRiskControversies(page, startPosition);


            _outlinePositions.Add(new Reporting.Framework.OutlinePosition { Name = "Controversies", PageNumber = 1 });
        }

        private void AddHighestRiskControversies(PdfReportPage page, float startPosition)
        {
            const string sectionName = "<p><b>CONTROVERSIES</b></p>";

            const float labelFontSize = 8f;
            const float labelWidth = 55f;
            var textWidth = 180f;

            var left = _report.LeftMargin;
            var top = startPosition;

            var assessments = new[] {"None", "Low", "Moderate", "Significant", "High", "Severe"};
            var assessmentColors = new[] {RgbColor.White, RgbColor.White, RgbColor.White, new RgbColor(252, 176, 64), new RgbColor(241, 89, 42), new RgbColor(191, 30, 46) };

            var style = new FormattedTextAreaStyle(Fonts.CalibriFontFamily, 6.5f, false)
            {
                Paragraph = { Align = TextAlign.Justify, Indent = 0, SpacingAfter = 5, AllowOrphanLines = false }
            };


            page.Elements.Add(new FormattedTextArea(sectionName, left, top, textWidth, _sectionNameFontSize + 2f, Fonts.CalibriFontFamily, _sectionNameFontSize, false));

            top += 20f;


            var lastUpdate = $"Last update: {_dataSource.CorporateData.LastControversyUpdate:MMM yyyy}";

            if (_dataSource.EventIndicators.Any())
            {
                page.Elements.Add(new Label(lastUpdate, left, top, textWidth,
                    8f + 2f, Fonts.CalibriRegular, 8f, TextAlign.Left, RgbColor.Black));
            }

            var maxTop = top + 20f;


            const string helpText = "<p>A Controversy is an event or an aggregation of ESG-related events that have negative impacts on stakeholders and/or the company. Controversies are a measure of company performance against its commitments and company involvement in Controversies may highlight inadequate company preparedness to manage its ESG risks.</p><p>A Controversy is rated on the following scale: Low, Moderate, Significant, High and Severe. This section of the report provides an assessment for controversies categorized as Significant, High and Severe.Controversies rated as Low or Moderate will not appear in this report.</p>";
            const string severeHelp = "<p>The event has a severe impact on the environment and society, posing serious risks to the company. This category represents the most egregious corporate behavior.</p>";
            const string highHelp = "<p>The event has a high impact on the environment and society, posing significant risks to the company. This category often reflects structural problems in the company.</p>";
            const string significantHelp = "<p>The event has a significant impact on the environment and society, posing moderate risks to the company.</p>";

            textWidth = 265f;
            left += 220f;
            top = startPosition;

            page.Elements.Add(new Rectangle(left, top, 325f, 195f, new RgbColor(240, 240, 240), new RgbColor(240, 240, 240)));
            top += 10f;

            var formattedTextArea = new FormattedTextArea(helpText, left + 15f, top, 295f, 300f, style);
            var textHeight = formattedTextArea.GetRequiredHeight() + 10f;

            page.Elements.Add(new FormattedTextArea(helpText, left + 15f, top, 295f, textHeight, style));
            top += textHeight + 10f;

            page.Elements.Add(new Label("SCALE", left + 15f, top, labelWidth, 10f + 2f, Fonts.CalibriBold, 10f, TextAlign.Left, RgbColor.Black));
            top += 20;

            page.Elements.Add(new Rectangle(left + 15f, top, labelWidth, 10f, assessmentColors[5], assessmentColors[5]));
            page.Elements.Add(new Label(assessments[5].ToUpperInvariant(), left + 15f, top + 1f, labelWidth, 10f, Fonts.CalibriRegular, labelFontSize, TextAlign.Center, RgbColor.White));
            page.Elements.Add(new FormattedTextArea(severeHelp, left + 80f, top, textWidth - 35f, 30f, style));
            top += 30;

            page.Elements.Add(new Rectangle(left + 15f, top, labelWidth, 10f, assessmentColors[4], assessmentColors[4]));
            page.Elements.Add(new Label(assessments[4].ToUpperInvariant(), left + 15f, top + 1f, labelWidth, 10f, Fonts.CalibriRegular, labelFontSize, TextAlign.Center, RgbColor.White));
            page.Elements.Add(new FormattedTextArea(highHelp, left + 80f, top, textWidth - 35f, 30f, style));
            top += 30;

            page.Elements.Add(new Rectangle(left + 15f, top, labelWidth, 10f, assessmentColors[3], assessmentColors[3]));
            page.Elements.Add(new Label(assessments[3].ToUpperInvariant(), left + 15f, top + 1f, labelWidth, 10f, Fonts.CalibriRegular, labelFontSize, TextAlign.Center, RgbColor.White));
            page.Elements.Add(new FormattedTextArea(significantHelp, left + 80f, top, textWidth - 35f, 30f, style));
            top += 40;

            page.Elements.Add(new Line(_report.LeftMargin, top, _report.LeftMargin + _report.PageMaxWidth, top, 0.5f, RgbColor.Gray));

            top += 20;

            if (!_dataSource.EventIndicators.Any())
            {
                const string noControversies = "We have not detected any major controversy for this company.";

                page.Elements.Add(new Label(noControversies, _report.LeftMargin, top, _report.PageMaxWidth, 10f, Fonts.CalibriRegular, 8f, TextAlign.Center, RgbColor.Black));
                return;
            }

            textWidth = 325f;


            style = new FormattedTextAreaStyle(Fonts.CalibriFontFamily, 8f, false)
            {
                Paragraph = { Align = TextAlign.Justify, Indent = 0, SpacingAfter = 5, AllowOrphanLines = false }
            };

            var remainingHeight = _report.PageMaxHeight - top;

            var controversyIndicatorNumber = string.Empty;

            foreach (var ei in _dataSource.EventIndicators)
            {
                var formattedSectionName = new FormattedTextArea($"{ei.ControversyIndicatorName} - {ei.Name}", left, top, textWidth, 500f, Fonts.CalibriFontFamily, _sectionNameFontSize + 2f, false);
                var textHeightSectionName = formattedSectionName.GetRequiredHeight() + 5f;


                formattedTextArea = new FormattedTextArea(ei.ControversySummary ?? string.Empty, left, top, textWidth, 500f, style);
                textHeight = formattedTextArea.GetRequiredHeight() + 30f;


                var estimatedHeight = remainingHeight - textHeightSectionName - textHeight - (controversyIndicatorNumber == ei.ControversyIndicatorNumber ? 20f : 40f);

                if (estimatedHeight <= 0)
                {
                    page = _report.NewPage();
                    _report.Pages.Add(page);

                    AddHeaderToPage(page);

                    top = startPosition;
                    remainingHeight = _report.PageMaxHeight - startPosition;
                }

                if (controversyIndicatorNumber != ei.ControversyIndicatorNumber)
                {
                    if (!top.NearlyEq(startPosition) && !string.IsNullOrEmpty(controversyIndicatorNumber))
                    {
                        page.Elements.Add(new Line(_report.LeftMargin, top, _report.LeftMargin + _report.PageMaxWidth, top, 0.5f, RgbColor.Gray));

                        top += 20;
                        remainingHeight = remainingHeight - 20;
                    }

                    var themeName = $"{(ei.ControversyIndicatorNumber == "E" ? "Environment" : ei.ControversyIndicatorNumber == "S" ? "Social" : ei.ControversyIndicatorNumber == "G" ? "Governance" : string.Empty)} Controversies";
                    page.Elements.Add(new Label(themeName, _report.LeftMargin, top, textWidth, _sectionNameFontSize + 2f, Fonts.CalibriLight, _sectionNameFontSize + 2f, TextAlign.Left, RgbColor.Black));
                }

                page.Elements.Add(new Rectangle(left, top, labelWidth, 10f, assessmentColors[ei.AnswerCategory], assessmentColors[ei.AnswerCategory]));
                page.Elements.Add(new Label(assessments[ei.AnswerCategory].ToUpperInvariant(), left, top + 1f, labelWidth, 10f, Fonts.CalibriRegular, labelFontSize, TextAlign.Center, RgbColor.White));
                top += 20;
                remainingHeight = remainingHeight - 20;


                page.Elements.Add(new FormattedTextArea($"{ei.ControversyIndicatorName} - {ei.Name}", 
                    left, top, textWidth, textHeightSectionName, Fonts.CalibriFontFamily, _sectionNameFontSize + 2f, false));
                top += textHeightSectionName;
                remainingHeight = remainingHeight - textHeightSectionName;


                page.Elements.Add(new FormattedTextArea(ei.ControversySummary ?? string.Empty, left, top, textWidth, textHeight, style));
                top += textHeight;
                remainingHeight = remainingHeight - textHeight;


                controversyIndicatorNumber = ei.ControversyIndicatorNumber;
            }
        }
    }
}
